/* 
CDX81 - The Calodox ZX81 Emulator
Copyright (c) 2003 Sebastian Gerlach

Uses code from the z81 emulator:
Original xz80 code Copyright (c) 1994 Ian Collier.
z81 changes        Copyright (c) 1995-2001 Russell Marks.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <malloc.h>

#define ZX_VID_WIDTH	(207*2)
#define ZX_VID_HEIGHT	314

struct Wave
{
	unsigned char *data;
	int length;
	int pos;
	int origin;

	Wave() { data=NULL; pos=length=origin=0; }
	~Wave() { if(data) free(data); }
	void load(const char *fname);
};

struct ZX81Emulator
{
	unsigned char video[ZX_VID_WIDTH*ZX_VID_HEIGHT+4000];
	unsigned char memory[65536];

	unsigned char keyports[9];

	unsigned char *memptr[64];
	int memattr[64];

	int nmigen,hsyncgen,vsync;

	unsigned int tstates;
	unsigned int lastDisplayPos;

	unsigned char a, f, b, c, d, e, h, l;
	unsigned char r, a1, f1, b1, c1, d1, e1, h1, l1, i, iff1, iff2, im;
	unsigned short pc;
	unsigned short ix, iy, sp;
	unsigned long nextlinetime;
	unsigned char radjust;
	unsigned char ixoriy, new_ixoriy;
	unsigned char intsample;
	unsigned char op;

	int ulacharline;
	int nmipend,intpend;
	int vsyncstart;

	Wave tapeSignal;

	typedef enum {
		ZX80 = 0,
		ZX81 = 1
	} Mode;

	Mode mode;

	void reset(Mode m, const unsigned char *rom, const char *fname);
	void runOneTick();

	void initmem(const unsigned char *rom);
	unsigned int in(int h,int l);
	unsigned int out(int h,int l,int a);

	void store(int x, unsigned char y) 
	{
		unsigned short off=(x)&1023;
		unsigned char page=(unsigned short)(x)>>10;
		int attr=memattr[page];
		if(attr)
			memptr[page][off]=y;
	}

	void store2b(int x, unsigned hi, unsigned lo) 
	{
		unsigned short off=(x)&1023;
		unsigned char page=(unsigned short)(x)>>10;
		int attr=memattr[page];
		if(attr) { 
			memptr[page][off]=(lo);
			memptr[page][off+1]=(hi);
		}
	}

	void store2(int x, unsigned y) 
	{
		store2b(x,(y)>>8,(y)&255);
	}

	unsigned fetch(int x) 
	{
		return memptr[(unsigned short)(x)>>10][(x)&1023];
	}

	unsigned fetch2(int x) 
	{
		return ((fetch((x)+1)<<8)|fetch(x));
	}

};


#define bc ((b<<8)|c)
#define de ((d<<8)|e)
#define hl ((h<<8)|l)
